/**
 * File    : GenericSelectModel.java
 * Created : 2008-10-19
 * By      : LuHuiguo
 */
package com.luhuiguo.tapestry.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.tapestry5.OptionGroupModel;
import org.apache.tapestry5.OptionModel;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.internal.OptionGroupModelImpl;
import org.apache.tapestry5.internal.OptionModelImpl;
import org.apache.tapestry5.ioc.services.PropertyAccess;
import org.apache.tapestry5.ioc.services.PropertyAdapter;
import org.apache.tapestry5.util.AbstractSelectModel;

/**
 * @author LuHuiguo
 * @version $Id: GenericSelectModel.java 18 2008-10-19 15:42:28Z LuHuiguo $
 * 
 */
public class GenericSelectModel<T> extends AbstractSelectModel implements
		ValueEncoder<T> {

	private PropertyAdapter labelFieldAdapter;
	private PropertyAdapter idFieldAdapter;
	private Collection<T> list;

	private List<OptionGroupModel> optionGroups;

	public GenericSelectModel(Collection<T> list, Class<T> clazz, String labelField,
			String idField, PropertyAccess access) {
		this.list = list;
		if (idField != null)
			this.idFieldAdapter = access.getAdapter(clazz).getPropertyAdapter(
					idField);
		if (labelField != null)
			this.labelFieldAdapter = access.getAdapter(clazz)
					.getPropertyAdapter(labelField);
	}

	public void addOptionGroup(String label, boolean disabled, List<T> options) {
		List<OptionModel> optionModels = new ArrayList<OptionModel>();
		if (labelFieldAdapter == null) {
			for (T obj : options) {
				optionModels.add(new OptionModelImpl(nvl(obj), obj));
			}
		} else {
			for (T obj : options) {
				optionModels.add(new OptionModelImpl(nvl(labelFieldAdapter
						.get(obj)), obj));
			}
		}

		if (optionGroups == null) {
			optionGroups = new ArrayList<OptionGroupModel>();
		}

		optionGroups.add(new OptionGroupModelImpl(label, disabled,
				optionModels, new String[0]));
	}

	@Override
	public List<OptionGroupModel> getOptionGroups() {
		return optionGroups;
	}

	@Override
	public List<OptionModel> getOptions() {
		List<OptionModel> optionModelList = new ArrayList<OptionModel>();
		if (labelFieldAdapter == null) {
			for (T obj : list) {
				optionModelList.add(new OptionModelImpl(nvl(obj)));
			}
		} else {
			for (T obj : list) {
				optionModelList.add(new OptionModelImpl(nvl(labelFieldAdapter
						.get(obj)), obj));
			}
		}
		return optionModelList;
	}

	@Override
	public String toClient(T value) {
		if (idFieldAdapter == null) {
			return value + "";
		} else {
			return idFieldAdapter.get(value) + "";
		}
	}

	@Override
	public T toValue(String clientValue) {
		if (idFieldAdapter == null) {
			for (T obj : list) {
				if (nvl(obj).equals(clientValue))
					return obj;
			}
		} else {
			for (T obj : list) {
				if (nvl(idFieldAdapter.get(obj)).equals(clientValue))
					return obj;
			}
		}
		return null;
	}

	private String nvl(Object o) {
		if (o == null)
			return "";
		else
			return o.toString();
	}
}
